﻿namespace Bowlus.FrontEnd.PortalAdminService
{
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.IO;
    using System.Linq;
    using System.Web.Script.Serialization;
    using Bowlus.Common;
    using Bowlus.Common.DeploymentActions;

    using Microsoft.WindowsAzure.ServiceRuntime;

    public class AdminService : IAdminService
    {
        public string GetTenantDeployment()
        {
            var tenantDep = TenantDeploymentsStore.Instance.TenantDeployment.ToList();

            var serializer = new JavaScriptSerializer();

            return serializer.Serialize(tenantDep);
        }

        /*
         * return application list: site1.1.zip, site1.2.zip, ect...
         */
        public string GetApplications()
        {
            var appRepository = new StorageAppRepository("System.ConnectionString");
            var appList = appRepository.GetAppList();

            var serializer = new JavaScriptSerializer();
            return serializer.Serialize(appList);
        }

        /*
         * return customization list: site1.1.1.zip, site1.1.2.zip, ect...
         */
        public string GetCustomizations(string application)
        {
            string appName = Path.GetFileNameWithoutExtension(application);
            IAppRepository appRepository = new StorageAppRepository("System.ConnectionString");
            Collection<string> custList = appRepository.GetCustomizationList(appName);

            var serializer = new JavaScriptSerializer();
            return serializer.Serialize(custList);
        }

        /// <summary>
        /// Create new tenant in Tenant deployment table. This tenant will later be allocated a instance, and then be deployed.
        /// </summary>
        /// <param name="tenantId">
        /// The tenant id.
        /// </param>
        /// <param name="application">
        /// The application.
        /// </param>
        /// <param name="customization"> </param>
        /// <returns>
        /// A status string
        /// </returns>
        public string CreateTenant(string tenantId, string application, string customization)
        {
            var tenantDeployment = new TenantDeployment
                {
                    Application = application,
                    Customizations = customization,
                    TenantId = tenantId,
                    HostName = Settings.TenantHostFromConfigFormat(tenantId),
                    DeploymentAction = DeploymentActionType.AddApplicationForHosting,
                    Status = TenantDeploymentStatus.Initializing
                };
            TenantDeploymentsStore.UpdateDeploymentStore(tenantDeployment);

            return "Request submitted.";
        }

        /*
         * Get instance health status.
         */
        public string GetInstanceStatus()
        {
            var healthStatus = new HealthStatus
                {
                    FrontEndInstances = new List<InstanceState>(),
                    AppHostInstances = new List<InstanceState>()
                };

            // TODO: Update this to use the service management API w/caching
            // RoleEnvironment information does not provide Status on an instance
            var roleInstances = RoleEnvironment.Roles[Settings.FrontEndRoleName];
            foreach (var instance in roleInstances.Instances)
            {
                healthStatus.FrontEndInstances.Add(new InstanceState { Title = instance.Id, Status = "Ready" });
            }

            roleInstances = RoleEnvironment.Roles[Settings.AppHostRoleName];
            var tenantDeployments = TenantDeploymentsStore.Instance.TenantDeployment.ToList();
            foreach (var instance in roleInstances.Instances)
            {
                try
                {
                    var instanceState = new InstanceState { Title = instance.Id, Status = "Ready" };
                    healthStatus.AppHostInstances.Add(instanceState);

                    var instance1 = instance;
                    var appsForHost = from tenantDeployment in tenantDeployments
                                      where tenantDeployment.AppHostInstanceId.Equals(instance1.Id)
                                      orderby tenantDeployment.TenantId
                                      select new InstanceStateItem { Text = tenantDeployment.TenantId, Status = tenantDeployment.Status };

                    instanceState.Items.AddRange(appsForHost.ToList());
                }
                catch (System.Data.Services.Client.DataServiceQueryException ex)
                {
                    BowlusLogger.LogError(ex.ToString());
                }
            }

            var serializer = new JavaScriptSerializer();

            return serializer.Serialize(healthStatus);
        }

        public string DeleteTenants(string tenants)
        {
            var serializer = new JavaScriptSerializer();
            var tenantsList = serializer.Deserialize(tenants, typeof(List<string>)) as List<string>;

            if (tenantsList == null)
            {
                return string.Empty;
            }

            var flattenedTenantsList = (from tenantData in tenantsList select tenantData.Split(',')).ToList();

            var tableContext = TenantDeploymentsStore.Instance;

            var updated = false;
            foreach (var tenantDeployment in tableContext.TenantDeployment)
            {
                if (!flattenedTenantsList.Any(
                    tdl => tdl[0].Trim().Equals(tenantDeployment.TenantId)
                           && tdl[1].Trim().Equals(tenantDeployment.AppHostInstanceId)))
                {
                    continue;
                }

                tenantDeployment.DeploymentAction = DeploymentActionType.DeleteApplicationFromHosting;
                tableContext.UpdateObject(tenantDeployment);
                updated = true;
            }

            if (updated)
            {
                tableContext.SaveChanges();
            }

            return string.Empty;
        }
    }
}
